home *** CD-ROM | disk | FTP | other *** search
/ Stone Design / Stone Design.iso / Stone_Friends / Wave / WavesWorld / Source / IBPalettes / WW3DKit / RIBCylinder.m < prev    next >
Encoding:
Text File  |  1995-05-13  |  9.7 KB  |  375 lines

  1. // copyright 1993 Michael B. Johnson; some portions copyright 1994, MIT
  2. // see COPYRIGHT for reuse legalities
  3. //
  4.  
  5. #import "RIBCylinder.h"
  6. #import <stdio.h>
  7.  
  8.  
  9. @implementation RIBCylinder
  10.  
  11.  
  12. + initialize { return [RIBCylinder setVersion:1], self; }
  13.  
  14. - (BOOL)hasBoundingBox { return YES; }
  15.  
  16. - init
  17. {
  18.   [super init];
  19.  
  20.   radius = 1.0;
  21.   zMin = -1.0;
  22.   zMax =  1.0;
  23.   
  24.   return self;
  25. }
  26.  
  27. - setRadius:(RtFloat)newRadius
  28.      zMin:(RtFloat)newZMin zMax:(RtFloat)newZMax 
  29.      thetaMax:(RtFloat)newThetaMax
  30.      n:(int)newN tokens:(RtToken *)newTokens parms:(RtPointer *)newParms archiveVector:(char **)newArchiveVector
  31.      printfTypeVector:(int *)newPrintfTypeVector printfNVector:(int *)newPrintfNVector
  32. {  
  33.    radius = newRadius;
  34.    zMin = newZMin;
  35.    zMax = newZMax;
  36.    thetaMax = newThetaMax;
  37.    [self setN:newN tokens:newTokens parms:newParms archiveVector:newArchiveVector printfTypeVector:newPrintfTypeVector printfNVector:newPrintfNVector];
  38.  
  39.    dirtyBoundingBox = TRUE;
  40.   
  41.    return self;
  42. }
  43.  
  44. - setRadius:(RtFloat)newRadius { radius = newRadius; dirtyBoundingBox = TRUE; return self; }
  45. - setZMin:(RtFloat)newZMin { zMin = newZMin; dirtyBoundingBox = TRUE; return self; }
  46. - setZMax:(RtFloat)newZMax { zMax = newZMax; dirtyBoundingBox = TRUE; return self; }
  47.  
  48. - (RtFloat)radius { return radius; } 
  49. - (RtFloat)zMin { return zMin; }
  50. - (RtFloat)zMax { return zMax; }
  51.  
  52. - calculateBoundingBoxStartingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  53. {
  54.   if (thetaMax >= 180.0)
  55.   {   boundingBox[0] =  -1.0 * radius;
  56.   }
  57.   else  // less than 180
  58.   {  if (thetaMax >= 90.0)
  59.      {  boundingBox[0] =  -1.0 * radius * (RtFloat)sin((double)(toRadians((thetaMax - 90.0))));
  60.      }
  61.      else
  62.      {  //boundingBox[0] =  radius * (RtFloat)sin((double)(toRadians(thetaMax)));
  63.         boundingBox[0] = 0.0;  // this is not true if zMax or abs(zMin) is less than radius
  64.      }
  65.   }
  66.   boundingBox[1] = radius;
  67.  
  68.   if (thetaMax >= 270.0)
  69.   {  boundingBox[2] = -1.0 * radius;
  70.      boundingBox[3] = radius;
  71.   }
  72.   else
  73.   {  if (thetaMax >= 180.0)
  74.      {  boundingBox[2] = radius * sin((double)(toRadians((thetaMax))));
  75.         boundingBox[3] = radius;
  76.      }
  77.      else
  78.      {  if (thetaMax >= 90.0)
  79.         {  boundingBox[2] = 0.0;
  80.            boundingBox[3] = radius;
  81.         }
  82.         else
  83.         {  boundingBox[2] = 0.0;
  84.            boundingBox[3] = radius * sin((double)(toRadians((thetaMax))));
  85.         }
  86.      }
  87.   }
  88.  
  89.   if (zMin < zMax)
  90.   {  boundingBox[4] = zMin;
  91.      boundingBox[5] = zMax;
  92.   }
  93.   else
  94.   {  boundingBox[4] = zMax;
  95.      boundingBox[5] = zMin;
  96.   }
  97.  
  98.   dirtyBoundingBox = FALSE; 
  99.  
  100.   return self;
  101. }
  102.  
  103.  
  104. - (BOOL)isMoot
  105. {
  106.   if (!radius) { return YES; }
  107.   if (zMin == zMax) { return YES; }
  108.  
  109.   return [super isMoot];
  110. }
  111.  
  112. - (BOOL)theSameAs:otherRIBCommand
  113. {
  114.   if (radius != [otherRIBCommand radius])
  115.   {  return NO;
  116.   }
  117.   if (zMin != [otherRIBCommand zMin])
  118.   {  return NO;
  119.   }
  120.   if (zMax != [otherRIBCommand zMax])
  121.   {  return NO;
  122.   }
  123.  
  124.   return [super theSameAs:otherRIBCommand];
  125. }
  126.  
  127.  
  128.  
  129.  
  130. - renderSelf:(WW3DCamera *)camera startingAt:(RtFloat)shutterOpenTime endingAt:(RtFloat)shutterCloseTime
  131. {
  132.   RiCylinderV(radius, zMin, zMax, thetaMax, n, tokens, parms);
  133.  
  134.   return self;
  135. }
  136.  
  137.  
  138. - (unsigned long int)maxSampleBandwidth {  return ([super maxSampleBandwidth] + (unsigned long int)(4 * sizeof(RtFloat))); }
  139.  
  140.  
  141. - (BOOL)isLerpable { return YES; }
  142.  
  143. // note: because we've made the WWSampleList "safe" for having
  144. // multiple samples with the same data, it's perfectly valid to return
  145. // yourself or b
  146. - lerpWith:b by:(float)uValue
  147. {
  148.    id      newMe = nil;
  149.    RtFloat radiusA, zMinA, zMaxA, thetaMaxA;
  150.    RtFloat radiusB, zMinB, zMaxB, thetaMaxB;
  151.  
  152.  
  153.    if (([self class] != [b class]) || (uValue <= 0.0))
  154.    {  return self;
  155.    }
  156.  
  157.    if (uValue >= 1.0)
  158.    {  return b;
  159.    }
  160.  
  161.    newMe = [super lerpWith:b by:uValue]; // this makes a copy for us
  162.  
  163.    // okay, now do the specific stuff for this class
  164.    radiusA = [self radius];
  165.    radiusB = [b radius];
  166.    [newMe setRadius:(radiusA + ((radiusB - radiusA) * uValue))]; 
  167.    zMinA = [self zMin];
  168.    zMinB = [b zMin];
  169.    [newMe setZMin:(zMinA + ((zMinB - zMinA) * uValue))];
  170.    zMaxA = [self zMax];
  171.    zMaxB = [b zMax];
  172.    [newMe setZMax:(zMaxA + ((zMaxB - zMaxA) * uValue))];
  173.    thetaMaxA = [self thetaMax];
  174.    thetaMaxB = [b thetaMax];
  175.    [newMe setThetaMax:(thetaMaxA + ((thetaMaxB - thetaMaxA) * uValue))];
  176.  
  177.    return newMe;
  178. }
  179.  
  180.  
  181. - lerpSelfWith:b by:(float)uValue
  182. {
  183.    RtFloat radiusA, zMinA, zMaxA, thetaMaxA;
  184.    RtFloat radiusB, zMinB, zMaxB, thetaMaxB;
  185.  
  186.  
  187.    if (([self class] != [b class]) || (uValue <= 0.0))
  188.    {  return self;
  189.    }
  190.  
  191.    if (uValue >= 1.0)
  192.    {  return b;
  193.    }
  194.  
  195.    [super lerpSelfWith:b by:uValue]; // this makes a copy for us
  196.  
  197.    // okay, now do the specific stuff for this class
  198.    radiusA = [self radius];
  199.    radiusB = [b radius];
  200.    [self setRadius:(radiusA + ((radiusB - radiusA) * uValue))]; 
  201.    zMinA = [self zMin];
  202.    zMinB = [b zMin];
  203.    [self setZMin:(zMinA + ((zMinB - zMinA) * uValue))];
  204.    zMaxA = [self zMax];
  205.    zMaxB = [b zMax];
  206.    [self setZMax:(zMaxA + ((zMaxB - zMaxA) * uValue))];
  207.    thetaMaxA = [self thetaMax];
  208.    thetaMaxB = [b thetaMax];
  209.    [self setThetaMax:(thetaMaxA + ((thetaMaxB - thetaMaxA) * uValue))];
  210.  
  211.    return self;
  212. }
  213.  
  214.  
  215. - writeEve:(NXStream *)stream atTabLevel:(int)tab
  216. {
  217.    int  i;
  218.  
  219.  
  220.    for (i = 0; i < tab; i++)
  221.    {  NXPrintf(stream, "\t");
  222.    }
  223.    NXPrintf(stream, "Cylinder %f %f %f %f ", radius, zMin, zMax, thetaMax);
  224.    [super writeParameterList:stream];
  225.    return self;
  226. }
  227.  
  228. - writeInventorAtTime:(float)currentTime to:(NXStream *)stream atTabLevel:(int)tab
  229. {
  230.    RtFloat umax;
  231.    RtFloat uknots[12];
  232.    RtFloat uk[12] = {0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1.0, 1.0, 1.0};
  233.    RtFloat vknots[4] = {0.0, 0.0, 1.0, 1.0};
  234.    RtFloat xuspline[9][2] = {{1.0, 0.0}, {M_SQRT1_2, -M_SQRT1_2}, {0.0, -1.0}, {-M_SQRT1_2, -M_SQRT1_2}, 
  235.                              {-1.0, 0.0}, {-M_SQRT1_2, M_SQRT1_2},  {0.0, 1.0}, {M_SQRT1_2, M_SQRT1_2}, {1.0, 0.0}};
  236.    RtFloat yuspline[9][2] = {{0.0, 1.0}, {M_SQRT1_2, M_SQRT1_2}, {1.0, 0.0}, {M_SQRT1_2, -M_SQRT1_2}, {0.0, -1.0}, 
  237.                            {-M_SQRT1_2, -M_SQRT1_2}, {-1.0, 0.0}, {-M_SQRT1_2, M_SQRT1_2}, {0.0, 1.0}};
  238.    RtFloat zwuspline[9] = {1.0, M_SQRT1_2, 1.0, M_SQRT1_2, 1.0, M_SQRT1_2, 1.0, M_SQRT1_2, 1.0};
  239.    int i, j, k;
  240.    RtPoint point1, point2;
  241.  
  242.  
  243.    point1[0] = [self radius];
  244.    point1[1] = 0.0;
  245.    point1[2] = [self zMin];
  246.    point2[0] = [self radius];
  247.    point2[1] = 0.0;
  248.    point2[2] = [self zMax];
  249.  
  250.    umax = [self thetaMax] / 360.0;
  251.    for (i=0; i<12; i++)
  252.    {  uknots[i] = uk[i] / umax;
  253.    }
  254.  
  255.    for (i = 0; i < tab; i++)
  256.    {  NXPrintf(stream, "\t");
  257.    }
  258.    NXPrintf(stream, "# ");
  259.    [self writeEve:stream atTabLevel:0];
  260.    NXPrintf(stream, "\n");
  261.  
  262.    for (i = 0; i < tab; i++)
  263.    {  NXPrintf(stream, "\t");
  264.    }
  265.    NXPrintf(stream, "# since Inventor doesn't directly support quadrics in any terribly useful way (sigh), we turn it into a NURBS surface:\n");
  266.  
  267.    for (i = 0; i < tab; i++)
  268.    {  NXPrintf(stream, "\t");
  269.    }
  270.    NXPrintf(stream, "Separator {\n");
  271.  
  272.    for (i = 0; i < (tab+1); i++)  {  NXPrintf(stream, "\t"); }
  273.    NXPrintf(stream, "Coordinate4 {\n");
  274.    for (i = 0; i < (tab+2); i++) {  NXPrintf(stream, "\t"); }
  275.    NXPrintf(stream, "point [");
  276.  
  277.    for (j=0; j<9; j++)
  278.    {  if (!j)
  279.       {  NXPrintf(stream, 
  280.           "%f %f %f %f,\n", 
  281.           (point1[0] * xuspline[j][0] + point1[1] * xuspline[j][1]),
  282.           (point1[0] * yuspline[j][0] + point1[1] * yuspline[j][1]),
  283.           (point1[2] * zwuspline[j]),
  284.           (zwuspline[j]));
  285.       }
  286.       else
  287.       {  NXPrintf(stream, 
  288.           "       %f %f %f %f,\n", 
  289.           (point1[0] * xuspline[j][0] + point1[1] * xuspline[j][1]),
  290.           (point1[0] * yuspline[j][0] + point1[1] * yuspline[j][1]),
  291.           (point1[2] * zwuspline[j]),
  292.           (zwuspline[j]));
  293.       }
  294.       for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  295.    }
  296.  
  297.    for (j=0; j<8; j++)
  298.    {  NXPrintf(stream, 
  299.            "       %f %f %f %f,\n", 
  300.            (point2[0] * xuspline[j][0] + point2[1] * xuspline[j][1]),
  301.            (point2[0] * yuspline[j][0] + point2[1] * yuspline[j][1]),
  302.            (point2[2] * zwuspline[j]),
  303.            (zwuspline[j]));
  304.       for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  305.    }
  306.    NXPrintf(stream, 
  307.         "       %f %f %f %f]\n", 
  308.         (point2[0] * xuspline[j][0] + point2[1] * xuspline[j][1]),
  309.         (point2[0] * yuspline[j][0] + point2[1] * yuspline[j][1]),
  310.         (point2[2] * zwuspline[j]),
  311.         (zwuspline[j]));
  312.  
  313.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  314.    NXPrintf(stream, "}\n");
  315.  
  316.    for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  317.    NXPrintf(stream, "NurbsSurface {\n");
  318.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  319.    NXPrintf(stream, "numUControlPoints 9\n");
  320.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  321.    NXPrintf(stream, "numVControlPoints 2\n");
  322.  
  323.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  324.    NXPrintf(stream, "uKnotVector [");
  325.    for (i=0; i<11; i++)
  326.    {    NXPrintf(stream, "%f, ", uknots[i]);
  327.    }
  328.    NXPrintf(stream, "%f]\n", uknots[i]);
  329.  
  330.    for (k = 0; k < (tab+2); k++) {  NXPrintf(stream, "\t"); }
  331.    NXPrintf(stream, "vKnotVector [");
  332.    for (i=0; i<3; i++)
  333.    {    NXPrintf(stream, "%f, ", vknots[i]);
  334.    }
  335.    NXPrintf(stream, "%f]\n", vknots[i]);
  336.  
  337.    for (k = 0; k < (tab+1); k++) {  NXPrintf(stream, "\t"); }
  338.    NXPrintf(stream, "}\n");
  339.    for (k = 0; k < tab; k++) {  NXPrintf(stream, "\t"); }
  340.    NXPrintf(stream, "}\n");
  341.  
  342.    return self;
  343. }
  344.  
  345. #define typeVector "fff"
  346. #define typeValues &radius, &zMin, &zMax
  347.  
  348. - read:(NXTypedStream*)stream 
  349. {
  350.     int version;
  351.     [super read:stream];
  352.  
  353.     version = NXTypedStreamClassVersion(stream,"RIBCylinder");
  354.     if (version == 0) NXReadTypes(stream,"i",&version), version=1;
  355.     if (version == 1)
  356.     {  NXReadTypes(stream,typeVector,typeValues);
  357.     } 
  358.     else 
  359.     {
  360.     }
  361.     return self;
  362. }
  363.  
  364. - write:(NXTypedStream*)stream 
  365. {
  366.     [super write:stream];
  367.  
  368.     NXWriteTypes(stream,typeVector, typeValues);
  369.  
  370.     return self;
  371. }
  372.  
  373.  
  374. @end
  375.